<template>
  <view class="u-read-more">
    <view
      class="u-read-more__content"
      :style="{
        height:
          isLongContent && status === 'close'
            ? $u.addUnit(showHeight)
            : $u.addUnit(contentHeight),
        textIndent: textIndent,
      }"
    >
      <view
        class="u-read-more__content__inner"
        ref="u-read-more__content__inner"
        :class="[elId]"
      >
        <slot></slot>
      </view>
    </view>
    <view
      class="u-read-more__toggle"
      :style="[innerShadowStyle]"
      v-if="isLongContent"
    >
      <slot name="toggle">
        <view class="u-read-more__toggle__text" @tap="toggleReadMore">
          <u--text
            :text="status === 'close' ? closeText : openText"
            :color="color"
            :size="fontSize"
            :lineHeight="fontSize"
            margin="0 5px 0 0"
          ></u--text>
          <view class="u-read-more__toggle__icon">
            <u-icon
              :color="color"
              :size="fontSize + 2"
              :name="status === 'close' ? 'arrow-down' : 'arrow-up'"
            ></u-icon>
          </view>
        </view>
      </slot>
    </view>
  </view>
</template>

<script>
// #ifdef APP-NVUE
const dom = uni.requireNativePlugin("dom");
// #endif
import props from "./props.js";
/**
 * readMore 阅读更多
 * @description 该组件一般用于内容较长，预先收起一部分，点击展开全部内容的场景。
 * @tutorial https://www.uviewui.com/components/readMore.html
 * @property {String | Number}	showHeight	内容超出此高度才会显示展开全文按钮，单位px（默认 400 ）
 * @property {Boolean}			toggle		展开后是否显示收起按钮（默认 false ）
 * @property {String}			closeText	关闭时的提示文字（默认 '展开阅读全文' ）
 * @property {String}			openText	展开时的提示文字（默认 '收起' ）
 * @property {String}			color		提示文字的颜色（默认 '#dc2626' ）
 * @property {String | Number}	fontSize	提示文字的大小，单位px （默认 14 ）
 * @property {Object}			shadowStyle	显示阴影的样式
 * @property {String}			textIndent	段落首行缩进的字符个数 （默认 '2em' ）
 * @property {String | Number}	name		用于在 open 和 close 事件中当作回调参数返回
 * @event {Function} open 内容被展开时触发
 * @event {Function} close 内容被收起时触发
 * @example <u-read-more><rich-text :nodes="content"></rich-text></u-read-more>
 */
export default {
  name: "u-read-more",
  mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
  data() {
    return {
      isLongContent: false, // 是否需要隐藏一部分内容
      status: "close", // 当前隐藏与显示的状态，close-收起状态，open-展开状态
      elId: uni.$u.guid(), // 生成唯一class
      contentHeight: 100, // 内容高度
    };
  },
  computed: {
    // 展开后无需阴影，收起时才需要阴影样式
    innerShadowStyle() {
      if (this.status === "open") return {};
      else return this.shadowStyle;
    },
  },
  mounted() {
    this.init();
  },
  methods: {
    async init() {
      this.getContentHeight().then((height) => {
        this.contentHeight = height;
        // 判断高度，如果真实内容高度大于占位高度，则显示收起与展开的控制按钮
        if (height > uni.$u.getPx(this.showHeight)) {
          this.isLongContent = true;
          this.status = "close";
        }
      });
    },
    // 获取内容的高度
    async getContentHeight() {
      // 延时一定时间再获取节点
      await uni.$u.sleep(30);
      return new Promise((resolve) => {
        // #ifndef APP-NVUE
        this.$uGetRect("." + this.elId).then((res) => {
          resolve(res.height);
        });
        // #endif

        // #ifdef APP-NVUE
        const ref = this.$refs["u-read-more__content__inner"];
        dom.getComponentRect(ref, (res) => {
          resolve(res.size.height);
        });
        // #endif
      });
    },
    // 展开或者收起
    toggleReadMore() {
      this.status = this.status === "close" ? "open" : "close";
      // 如果toggle为false，隐藏"收起"部分的内容
      if (this.toggle == false) this.isLongContent = false;
      // 发出打开或者收齐的事件
      this.$emit(this.status, this.name);
    },
  },
};
</script>

<style lang="scss" scoped>
@import "../../libs/css/components.scss";

.u-read-more {
  &__content {
    overflow: hidden;
    color: $u-content-color;
    font-size: 15px;
    text-align: left;
  }

  &__toggle {
    @include flex;
    justify-content: center;

    &__text {
      @include flex;
      align-items: center;
      justify-content: center;
      margin-top: 5px;
    }
  }
}
</style>
